/**
 * @author wudx
 * @description 生成差异文件配置
 */

var program = require('commander');
var fs = require("fs");
var path = require("path");
var crypto = require('crypto');
var xml2js = require("xml2js");

// program
// .version('0.1.0')
// .option('-i, --input <input>', '输入目录')
// .option('-o, --output <output>', '输出目录')
// .option('-n, --versionName <versionName>', '版本号')
// .option('-m, --maxCount <maxCount>', '最大差异数量，超过就重置大版本号')
// .parse(process.argv);

// if(!program.input){
//     console.log("缺少输入目录");
//     process.exit(1);
// }
// if(!program.output){
//     console.log("缺少输出目录");
//     process.exit(1);
// }
program
.version('0.1.0')
.option('-c, --config <config>', '读取配置文件')
.parse(process.argv);

if(!program.config){
    console.log("缺少配置文件");
    process.exit(1);
}
console.log("开始比较...");

var inputPath;
var outPath;
var isCopyFile;
var ignoreDirs=[];
var allFiles = [];
var recordFilePath;
var recordData="";
var recordFiles="";
var recordCount = 0;
var modifyFileCount = 0;
var oldRecordData;
var isFirstRecord = false;
var versionFilePath;
var versionData="";
var versionFiles=[];
var versionDic = {};
var maxDiffCount = 2000;
var oldVersion;
var newVersion = generaVersion();
var stream = fs.readFileSync(program.config);
xml2js.parseString(stream, { explicitArray : false },(err,result)=>{
    result = result["config"];
    inputPath = result["inputDir"];
    outPath = result["outputDir"];
    isCopyFile = result["isCopyFile"]=='true';
    maxDiffCount = parseInt(result["maxDiffCount"]);
    newVersion = result["versionName"];
    ignoreDirs = result["ignoreDirs"].split("|");


    if(!newVersion){
        newVersion = generaVersion();
    }

    readHistory();
});

function readHistory(){

    var dirs = outPath.split("\\");
    var curDir = "";
    while(dirs.length > 0){
        curDir += dirs.shift()+"\\";
        if(!exists(curDir)){
            fs.mkdirSync(curDir);
        }
    }

    recordFilePath = path.join(outPath,".history");
    versionFilePath = path.join(outPath,"version.json");

    if(!exists(versionFilePath)){
        fs.createWriteStream(versionFilePath);
    }
    
    if(!exists(recordFilePath)){
        isFirstRecord = true;
        fs.createWriteStream(recordFilePath);
        compare();
    }else{
        var stream = fs.readFileSync(recordFilePath);
        xml2js.parseString(stream, { explicitArray : false },(err,result)=>{
            if(result.hasOwnProperty("root") && result["root"].hasOwnProperty("file")){
                var files = result["root"]["file"];
                oldVersion = result["root"]["version"];
                files.forEach((item,index,array)=>{
                    versionDic[item.name]=item;
                })
            }
            compare();
        });
    }
}

function compare(){
    readFile(inputPath);
    parseFile();
}

function readFile(inputDir){
    var files = fs.readdirSync(inputDir);
    files.forEach((value,index,array)=>{
        var file = path.join(inputDir,value);
        var stat = fs.statSync(file);
        var subDir = cutInputDir(file);
        if(stat.isDirectory()){
            //console.log(file,subDir)
            if(ignoreDirs.indexOf(subDir) == -1){
                readFile(file);
            }
        }else{
            if(ignoreDirs.indexOf(subDir) == -1){//忽略文件要包含路径
                allFiles.push(file);
            }
        }
    })
}

function parseFile(){
    if(allFiles.length > 0){
        var file = allFiles.shift();
        md5(file);
    }else{

        recordData="<root>\n"
        var useVersion;
        if(isFirstRecord){
            useVersion = newVersion;
            console.log("创建版本差异数据,共记"+recordCount+"个文件\n");

            versionFiles=[];
        }else if(modifyFileCount >= maxDiffCount){
            useVersion = newVersion;
            console.log("差异文件："+modifyFileCount+"个,超过最大上限，更新大版本号\n");

            versionFiles=[];
        }else{
            useVersion = oldVersion;
            console.log("差异文件："+modifyFileCount+"个\n");
        }

        recordData+="<version>"+useVersion+"</version>\n"
        recordData+=recordFiles;
        recordData+='</root>\n';
        writeFile(recordFilePath,recordData);

        versionData="{\n";
        versionFiles.forEach((value,index)=>{
            versionData+=value;
            if(index != versionFiles.length-1){
                versionData+=",\n";
            }
        })
        versionData+="\n}";
        writeFile(versionFilePath,versionData);
        console.log("完成版本差异化\n");
    }
}


function generaVersion(){
    var date = new Date();
    var hour = date.getHours();
    var minute = date.getMinutes();
    var sec = date.getSeconds();
    return date.getFullYear()+""+fixTime(date.getMonth()+1)+""+fixTime(date.getDate())+""+fixTime(hour)+""+fixTime(minute)+""+fixTime(sec);
}
function fixTime(value){
    if(value < 10)
        return "0"+value;
    return value;
}

function md5(filePath){
    var md5sum = crypto.createHash('md5');
    var stream = fs.createReadStream(filePath);
    stream.on('data', function(chunk) {
        md5sum.update(chunk);
    });
    stream.on('end', function() {
        str = md5sum.digest('hex').toUpperCase();
        var lineStr = "<file>";
        subFile = filePath.slice(inputPath.length+1,filePath.length);
        lineStr+="<name>"+subFile+"</name>";
        
        if(isFirstRecord){
            recordCount++;
            console.log(subFile,newVersion);
            lineStr+="<version>"+newVersion+"</version>";
        }else{
            if(!versionDic[subFile]){//新添加文件
                versionFiles.push('"'+subFile.replace(/\\/g,"\\/")+'":"'+newVersion+'"');
                modifyFileCount++;
                console.log("+  "+subFile,newVersion);
                moveFile(filePath)

                lineStr+="<version>"+newVersion+"</version>";
            }else if(versionDic[subFile].md5 != str){//与上一版的差异文件
                versionFiles.push('"'+subFile.replace(/\\/g,"\\/")+'":"'+newVersion+'"');
                modifyFileCount++;
                moveFile(filePath)
                console.log("*  "+subFile,newVersion);

                lineStr+="<version>"+newVersion+"</version>";
            }else{
                if(versionDic[subFile].version != oldVersion){//历史差异文件
                    console.log("**  "+subFile,versionDic[subFile].version);
                    versionFiles.push('"'+subFile.replace(/\\/g,"\\/")+'":"'+versionDic[subFile].version+'"');
                    modifyFileCount++;
                    moveFile(filePath)
                }
                lineStr+="<version>"+versionDic[subFile].version+"</version>";
            }
        }
        lineStr+="<md5>"+str+"</md5>";
        lineStr+="</file>\n";
        recordFiles+= lineStr;
        parseFile();
    });
}

function moveFile(file){
    if(isCopyFile){
        var versionFile = path.join(outPath,newVersion);
        if(!exists(versionFile)){
            fs.mkdirSync(versionFile);
        }
    
        var subDir = cutInputDir(file);
        var subDirs = subDir.split("\\");
        subDirs.pop();
        var curDir=path.join(outPath,newVersion);
        while(subDirs.length > 0){
            curDir = path.join(curDir,subDirs.shift());
            if(!exists(curDir)){
                fs.mkdirSync(curDir);
            }
        }
        
        var outFile = path.join(outPath,newVersion,cutInputDir(file));
        fs.writeFileSync(outFile, fs.readFileSync(file));
    }
}

function cutInputDir(filePath){
    return filePath.replace(inputPath+"\\","");
}
function exists(path){  
    return fs.existsSync(path);
} 

function writeFile(path,data){
    fs.writeFileSync(path,data)
}
